/************************************************************************
This file is part of Polar4linux
Copyright (C) 2010-2011 Eric jrdn2
Portions Copyright (C) 2007 Matti Juvonen <mpj@iki.fi> (RS400 Tools)
Portions Copyright (C) 2006 Jani Hursti <jani.hursti@hut.fi>,
Portions Copyright (C) 2001-2003 Tom Oliveira e Silva

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
************************************************************************/

#include "pageView.h"

pageView::pageView(QWidget *parent) : QGraphicsView(parent)
{
	onlinescene = new QGraphicsScene(this);
	setScene(onlinescene);
	setMouseTracking(true);
	previewscene = new QGraphicsScene(this);
	setLayout(1,1);
	selectionRect=NULL;
	selectedGraph=NULL;
	selectionRect=NULL;
	lastHoveredGraph=0;
}

pageView::~pageView()
{
	clearPage();
}

void pageView::clearPage()
{
	for (unsigned int i=0;i<graphs.size();i++) delete graphs[i];
	removeGraphs();
}

void pageView::removeGraphs()
{
	graphs.clear();
}

void pageView::clearSelectedGraph()
{
	if (selectedGraph!=NULL)
	{
		std::vector<graph*>::iterator it= std::find(graphs.begin(),graphs.end(),selectedGraph);
		if (it!=graphs.end())
		{
			graphs.erase(it);
			delete selectedGraph;
			plotPage();
		}
	}
	if (graphs.size()==0) emit pageIsEmpty();
	std::cout<<"graph is removed"<<std::endl;
}

void pageView::addGraph(graph* g)
{
	graphs.push_back(g);
	selectedGraph=graphs[0]; //so that value is always initialized to something
	lastHoveredGraph=0;
}

void pageView::computeBBox(graph *g, int posh,int posv,int nbthumbh,int nbthumbv, int totalh, int totalv)
{
	g->setScene(scene());

	float availablewidth=totalh/(float)nbthumbh;
	float availableheight=totalv/(float)nbthumbv;
	
	float ratio1=availablewidth/800.0;
	float ratio2=availableheight/400.0;
	
	g->box.ratio2normal=ratio1<ratio2?ratio1:ratio2;
	if (g->box.ratio2normal>1) g->box.ratio2normal=1;

	float margin=10*g->box.ratio2normal;
	g->box.myfontsize=12*g->box.ratio2normal;
	g->box.myfont.setPixelSize(g->box.myfontsize);
	
//compute graph parameters
	g->box.THUMBOX=(posh)*availablewidth;
	g->box.THUMBOY=(posv)*availableheight;

	g->box.THUMBWIDTH=availablewidth;
	g->box.THUMBHEIGHT=availableheight;

	g->box.GRAPHOX=g->box.THUMBOX+30*g->box.ratio2normal+margin;
	g->box.GRAPHOY=g->box.THUMBOY+30*g->box.ratio2normal+margin;
	
	g->box.GRAPHWIDTH=g->box.THUMBWIDTH-100*g->box.ratio2normal;
	g->box.GRAPHHEIGHT=g->box.THUMBHEIGHT-200*g->box.ratio2normal;

	g->box.LEGEND1_OX=g->box.GRAPHOX;
	g->box.LEGEND1_OY=g->box.GRAPHOY+g->box.GRAPHHEIGHT+50*g->box.ratio2normal;
	
	g->box.LEGEND2_OX=g->box.LEGEND1_OX+260*g->box.ratio2normal;
	g->box.LEGEND2_OY=g->box.LEGEND1_OY;

	g->box.HISTOGRAM_OX=g->box.GRAPHOX+g->box.GRAPHWIDTH-200*g->box.ratio2normal;
	g->box.HISTOGRAM_OY=g->box.LEGEND1_OY+60*g->box.ratio2normal;
}


void pageView::computeBBoxPreview(graph *g, int posh,int posv,int nbthumbh,int nbthumbv, int totalh, int totalv)
{
	g->setScene(previewscene);
	
	float availablewidth=totalh/(float)nbthumbh;
	float availableheight=totalv/(float)nbthumbv;
	
	float ratio1=availablewidth/800.0;
	float ratio2=availableheight/400.0;
	
	g->box.ratio2normal=ratio1<ratio2?ratio1:ratio2;
	if (g->box.ratio2normal>1) g->box.ratio2normal=1;
	
//compute graph parameters
	g->box.THUMBOX=(posh)*availablewidth;
	g->box.THUMBOY=(posv)*availableheight;

	g->box.THUMBWIDTH=availablewidth;
	g->box.THUMBHEIGHT=availableheight;

	g->box.GRAPHOX=g->box.THUMBOX+30*g->box.ratio2normal;
	g->box.GRAPHOY=g->box.THUMBOY+30*g->box.ratio2normal;

	g->box.GRAPHHEIGHT=g->box.THUMBHEIGHT-100*g->box.ratio2normal; //-200*ratio2normal;
	g->box.GRAPHWIDTH=g->box.THUMBWIDTH-100*g->box.ratio2normal; //-100*ratio2normal;

	g->box.LEGEND1_OX=g->box.GRAPHOX;
	g->box.LEGEND1_OY=g->box.GRAPHOY+g->box.GRAPHHEIGHT+50*g->box.ratio2normal;
	
	g->box.LEGEND2_OX=g->box.LEGEND1_OX+260*g->box.ratio2normal;
	g->box.LEGEND2_OY=g->box.LEGEND1_OY;

	g->box.HISTOGRAM_OX=g->box.GRAPHOX+g->box.GRAPHWIDTH-200*g->box.ratio2normal;
	g->box.HISTOGRAM_OY=g->box.LEGEND1_OY+60*g->box.ratio2normal;

	g->box.myfontsize=12*g->box.ratio2normal;
	g->box.myfont.setPixelSize(g->box.myfontsize);
}

void pageView::saveImage(QGraphicsScene *scene,QString filename)
{
	//don't save selection rectangle
	if (selectionRect!=NULL) scene->removeItem(selectionRect);
	QSize resultSize(width()-2*extraMargin, height()-2*extraMargin);
	QImage sourceImage = QImage(resultSize, QImage::Format_ARGB32_Premultiplied);
	QPainter p(&sourceImage);
  const QRectF target(0.0, 0.0, width(), height());
  const QRectF source(0, 0, width(), height());
	scene->render(&p,target,source,Qt::KeepAspectRatio);
	p.end();
	sourceImage.save(filename, "PNG");
	//redraw selection rectangle
	highlightSelection();
}


void pageView::associate(polar4linuxInternals *internals0)
{
	internals=internals0;
}


void pageView::resizeEvent ( QResizeEvent* /*event*/ )
{
	//replot
	plotPage();
}

void pageView::highlightSelection()
{
	if (selectedGraph!=NULL && graphs.size()!=1)
	{
		gBrush.setStyle(Qt::NoBrush);
		gPen.setColor(Qt::black);
		gPen.setWidth(2.0);
		bbox* b=&selectedGraph->box;
		selectionRect=scene()->addRect(QRectF(b->THUMBOX,b->THUMBOY,b->THUMBWIDTH,b->THUMBHEIGHT),gPen,gBrush);
		selectionRect->setZValue(1000);
	}
}

void pageView::plotPage()
{
	show();
	qDeleteAll( scene()->items() );
	selectionRect=NULL;
	gBrush.setStyle(Qt::SolidPattern);
	gPen.setColor(Qt::white);
	gBrush.setColor(Qt::white);

	setSceneRect(-extraMargin,-extraMargin,width()-extraMargin,height()-extraMargin);
	scene()->addRect(QRectF(-10,10,width()+10,height()+10),gPen,gBrush)->setZValue(-1000002);// background, do not see all

	setLayout(1,graphs.size());
	for (unsigned int i=0;i<graphs.size();i++)
	{
		computeBBox(graphs[i],0,i,nbthumbh,nbthumbv,width()-2.0*extraMargin,height()-2.0*extraMargin);
		graphs[i]->plot();
	}
	highlightSelection();
}


void pageView::plotPreview(graph &g)
{
	computeBBoxPreview(&g,0,0,1,1,previewWidth,previewHeight);
	g.plotPreview(previewWidth,previewHeight);

	QSize resultSize(previewWidth, previewHeight);
	QImage sourceImage = QImage(resultSize, QImage::Format_ARGB32_Premultiplied);
	QPainter p(&sourceImage);
	const QRectF target(0, 0, previewWidth, previewHeight);
	const QRectF source(0, 0, previewWidth, previewHeight);
	previewscene->render(&p,target,source,Qt::KeepAspectRatio);
	p.end();

	internals->imagePreview=sourceImage.scaled(QSize(previewWidth,previewHeight),Qt::KeepAspectRatio);
}



void pageView::setLayout(int h,int v)
{
	nbthumbh=h;
	nbthumbv=v;
}

unsigned int pageView::gimmeGraphNum( QMouseEvent * event )
{
	QPointF tmp1 = mapToScene(event->pos());
	float availablewidth=width()/(float)nbthumbh;
	float availableheight=height()/(float)nbthumbv;
	int posh=tmp1.x()/availablewidth;
	int posv=tmp1.y()/availableheight;
	posh = posh<0?0:posh;
	posv = posv<0?0:posv;
	posh = posh>=(nbthumbh-1)?(nbthumbh-1):posh;
	posv = posv>=(nbthumbv-1)?(nbthumbv-1):posv;
	return (unsigned int)(posv*nbthumbh+posh);
}

void pageView::mousePressEvent(QMouseEvent *event)
{
	unsigned int n0=gimmeGraphNum(event);
	if (n0<graphs.size())
	{
		selectedGraph=graphs[n0];
		if (selectionRect!=NULL) scene()->removeItem(selectionRect);
		highlightSelection();
		QPointF tmp1 = mapToScene(event->pos());
		QPointF pta = mapToGlobal(event->pos());
		int ret=selectedGraph->mousePressEvent(event->button(),tmp1);
		if (ret && event->button()==Qt::RightButton)
		{
			QMenu * menu = new QMenu(QObject::tr("name"), this);
			QAction *ac = new QAction(QObject::tr("Remove graph "), this);
			ac->setData(n0);
			menu->addAction(ac);
			connect(ac, SIGNAL(triggered()), this, SLOT(clearSelectedGraph()));
			menu->move(pta.x(), pta.y());
			menu->show(); 
		}
	}
}


void pageView::mouseMoveEvent ( QMouseEvent * event )
{
	unsigned int n0=gimmeGraphNum(event);
	if (n0<graphs.size())
	{
		if (lastHoveredGraph<graphs.size()) graphs[lastHoveredGraph]->leave(); //happens when deleting last graph
		lastHoveredGraph=n0;
		graph *g=graphs[n0];
		QPointF tmp1 = mapToScene(event->pos());
		g->mouseMoveEvent(tmp1);
	}
}

void pageView::mouseReleaseEvent(QMouseEvent *event)
{
	unsigned int n0=gimmeGraphNum(event);
	if (n0<graphs.size())
	{
		graph *g=graphs[n0];
		QPointF tmp1 = mapToScene(event->pos());
		g->mouseReleaseEvent(event->button(),tmp1);
	}
}
